//-----------------------------------------------------------------------
// <copyright file="Changes.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation.  All rights reserved.
// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY 
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
// </copyright>
// <author>Giles Knap [Updated 03 Apr 08: Mike Fourie - Code Cleanup, TFS 2008 Support, Workingdirectory Support etc.]</author>
// <date>2006-03-23</date>
// <summary>Returns a Changelist number for a given DateTime and Team Source filespec.</summary>
//-----------------------------------------------------------------------

namespace Microsoft.Sdc.Tasks.SourceTfs
{
    using System.Globalization;
    using System;
    using Microsoft.Build.Framework;
    using Microsoft.Sdc.Tasks.Configuration;

    /// <summary>
    /// Returns true if there have been changes since a given label.
    /// </summary>
    /// <remarks>
    /// <code><![CDATA[
    /// <SourceTfs.Changes Path="path" Label="label" TfsVersion="tfsVersion" WorkingDirectory="workingDirectory"/>]]></code>
    /// <para>where:</para>
    /// <para><i>path (Required)</i></para>
    /// <para>The full path to the file or folder.</para>
    /// <para><i>label (Required)</i></para>
    /// <para>The DateTime over which changes will be returned.</para>
    /// </remarks>
    /// <example>
    /// <code><![CDATA[
    /// <Project>
    ///     <Target Name="Test" >
    ///         <SourceTfs.Changes
    ///             Path="hum.c"
    ///             Label="2003/05/01" >
    ///             <Output TaskParameter="ChangesFound" PropertyName="ChangesFoundItem" />
    ///         </SourceTfs.Changes>
    ///     </Target>
    /// </Project>
    /// ]]></code>    
    /// </example>
    public class Changes : TaskBase
    {
        private string path;
        private string label;
        private bool changesFound;
        private string tfsVersion = "2005";
        private string workingDirectory;

        /// <summary>
        /// Gets or sets the working directory.
        /// </summary>
        /// <value>The working directory.</value>
        public string WorkingDirectory
        {
            get { return this.workingDirectory; }
            set { this.workingDirectory = value; }
        }

        /// <summary>
        /// Gets or sets the TFS version.
        /// </summary>
        /// <value>The TFS version.</value>
        public string TfsVersion
        {
            get { return this.tfsVersion; }
            set { this.tfsVersion = value; }
        }

        /// <summary>
        /// Gets or sets a value indicating whether [changes found].
        /// </summary>
        /// <value><c>true</c> if [changes found]; otherwise, <c>false</c>.</value>
        [Output]
        public bool ChangesFound
        {
            get { return this.changesFound; }
            set { this.changesFound = value; }
        }

        /// <summary>Gets or sets the path to the file or folder.</summary>
        /// <value>The full path to the file or folder.</value>
        [Required]
        public string Path
        {
            get { return this.path; }
            set { this.path = value; }
        }

        /// <summary>
        /// Gets or sets the DateTime over which changes will be returned
        /// </summary>
        /// <value>The DateTime over which changes will be returned</value>
        [Required]
        public string Label
        {
            get { return this.label; }
            set { this.label = value; }
        }

        /// <summary>
        /// Performs the action of this task.
        /// </summary>
        protected override void InternalExecute()
        {
            int changelistForLabel;
            int changelistCurrent;
            this.changesFound = false;
            Helper h = new Helper(this.TfsVersion);
            string arguments = String.Format(CultureInfo.InvariantCulture, "history \"{0}\" /version:L{1}  /format:brief /noprompt /recursive /stopafter:1", this.path, this.label);
            ShellExecute shellExecute = new ShellExecute(h.TfExePath, arguments);
            if (string.IsNullOrEmpty(this.WorkingDirectory) == false)
            {
                shellExecute.WorkingDirectory = this.WorkingDirectory;
            }

            Log.LogMessage(MessageImportance.Normal, string.Format("Executing {0} with {1}", shellExecute.Filename, arguments));
            int returnValue = shellExecute.Execute();
            Log.LogMessage(MessageImportance.Low, shellExecute.StandardOutput);

            switch (returnValue)
            {
                case 1:
                    Log.LogWarning("Exit Code 1. Partial success: " + shellExecute.StandardError.Trim());
                    break;
                case 2:
                    Log.LogError("Exit Code 2. Unrecognized command: " + shellExecute.StandardError.Trim());
                    break;
                case 100:
                    Log.LogError("Exit Code 100. Nothing Succeeded: " + shellExecute.StandardError.Trim());
                    break;
            }

            if (shellExecute.StandardOutput.Length == 0)
            {
                return;
            }

            string lastLine = Helper.FindLastLine(shellExecute.StandardOutput);
            string[] changeParts = lastLine.Split(' ');
            changelistForLabel = Convert.ToInt32(changeParts[0], CultureInfo.InvariantCulture);

            arguments = String.Format(CultureInfo.InvariantCulture, "history \"{0}\"  /format:brief /noprompt /recursive /stopafter:1", this.path);
            shellExecute = new ShellExecute(h.TfExePath, arguments);
            if (string.IsNullOrEmpty(this.WorkingDirectory) == false)
            {
                shellExecute.WorkingDirectory = this.WorkingDirectory;
            }

            Log.LogMessage(MessageImportance.Normal, string.Format("Executing {0} with {1}", shellExecute.Filename, arguments));
            returnValue = shellExecute.Execute();
            Log.LogMessage(MessageImportance.Low, shellExecute.StandardOutput);

            switch (returnValue)
            {
                case 1:
                    Log.LogWarning("Exit Code 1. Partial success: " + shellExecute.StandardError.Trim());
                    break;
                case 2:
                    Log.LogError("Exit Code 2. Unrecognized command: " + shellExecute.StandardError.Trim());
                    break;
                case 100:
                    Log.LogError("Exit Code 100. Nothing Succeeded: " + shellExecute.StandardError.Trim());
                    break;
            }

            if (shellExecute.StandardOutput.Length == 0)
            {
                return;
            }

            lastLine = Helper.FindLastLine(shellExecute.StandardOutput);
            changeParts = Helper.SplitColumns(lastLine);
            changelistCurrent = Convert.ToInt32(changeParts[0], CultureInfo.InvariantCulture);

            if (changelistCurrent > changelistForLabel)
            {
                this.changesFound = true;
            }
        }
    }
}